﻿Public Class clsLog
#Region " IDisposable Support "
    Implements IDisposable
    Private disposedValue As Boolean = False        ' 偵測多餘的呼叫
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: 明確呼叫時釋放 Managed 資源
                Me.FlashLog()
            End If

            ' TODO: 釋放共用的 Unmanaged 資源
        End If
        Me.disposedValue = True
    End Sub

    ' 由 Visual Basic 新增此程式碼以正確實作可處置的模式。
    Public Sub Dispose() Implements IDisposable.Dispose
        ' 請勿變更此程式碼。在以上的 Dispose 置入清除程式碼 (ByVal 視為布林值處置)。
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

    Private outPath As String = ""
    Private outFile As String = ""
    Private Const LogSizeMax As Int32 = 500 * 1024
    Private Const FileCountMax As Int32 = 50
    Private logQueue(1) As Queue(Of String)
    Private CurQueue As Int32 = 0
    Private WithEvents tmrWrite As System.Timers.Timer

    Public Sub AddLog(ByVal s As String)
        SyncLock logQueue
            logQueue(CurQueue).Enqueue(Format(Now, "yyyy/MM/dd HH:mm:ss") & ":" & vbTab & s)
        End SyncLock
    End Sub

    Private Sub WriteLog()
        If My.Computer.FileSystem.DirectoryExists(outPath) = False Then
            My.Computer.FileSystem.CreateDirectory(outPath)
        End If

        SyncLock logQueue
            If logQueue(CurQueue).Count > 0 Then
                'swap queue
                CurQueue = 1 - CurQueue
            End If
        End SyncLock
        If logQueue(1 - CurQueue).Count > 0 Then
            If My.Computer.FileSystem.FileExists(outFile) Then
                If My.Computer.FileSystem.GetFileInfo(outFile).Length >= LogSizeMax Then
                    My.Computer.FileSystem.RenameFile(outFile, Format(Now, "yyyyMMdd_HHmmss") & ".log")
                    Dim lstFiles() As IO.FileInfo = My.Computer.FileSystem.GetDirectoryInfo(outPath).GetFiles("*.log")
                    If lstFiles.Length > FileCountMax Then
                        Dim idx As Int32 = 0
                        Dim minMT As Date = lstFiles(0).LastWriteTime
                        For i As Int32 = 1 To lstFiles.Length - 1
                            If lstFiles(i).LastWriteTime > minMT Then
                                minMT = lstFiles(i).LastWriteTime
                                idx = i
                            End If
                        Next
                        If idx >= 0 AndAlso idx < lstFiles.Length Then
                            Try
                                My.Computer.FileSystem.DeleteFile(lstFiles(idx).FullName)
                            Catch ex As Exception

                            End Try
                        End If
                    End If
                End If
            End If
            Dim s As String = ""
            While logQueue(1 - CurQueue).Count > 0
                s += (logQueue(1 - CurQueue).Dequeue & vbCrLf)
            End While
            My.Computer.FileSystem.WriteAllText(outFile, s, True)
        End If
    End Sub

    Private Sub tmrWrite_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles tmrWrite.Elapsed
        Me.WriteLog()
    End Sub

    Private Sub FlashLog()
        Me.tmrWrite.Dispose()
        Me.WriteLog()
        SyncLock logQueue
            For i As Int32 = 0 To 1
                logQueue(i).Clear()
            Next
        End SyncLock
    End Sub

    Sub New(ByVal LogPath As String)
        outPath = LogPath
        outFile = LogPath & "\Current.log"
        For i As Int32 = 0 To 1
            logQueue(i) = New Queue(Of String)
        Next
        CurQueue = 0
        Me.tmrWrite = New System.Timers.Timer(1000)
        Me.tmrWrite.Enabled = True
    End Sub
End Class
